'''
Created on 21/10/2012

@author: Chris
'''

import xml.etree.ElementTree as ET
import os, re
from util import report_exception

g_work_dir = ""
g_cnfg_dir = ""
g_temp_dir = ""
g_repo_file = ""
g_log_file  = ""
g_default_compare_tool = "WinMergeU"

#=======================================================================================
def init_app_env():
#=======================================================================================
    global g_work_dir
    global g_cnfg_dir
    global g_repo_file
    global g_log_file
    global g_temp_dir

    current_work_path = os.getcwd()
    
    regex = r"\S+DrafteManager"
    patrn = re.compile(regex)

    g_work_dir = patrn.match(current_work_path).group()+"\\"
    g_cnfg_dir = g_work_dir + "config\\"
    g_log_file = g_work_dir + "log\\dm.log"
    g_repo_file = g_cnfg_dir + "repository.xml"
    g_temp_dir  = g_work_dir + "temp\\"

    if not os.path.exists(g_cnfg_dir):
        #create config directory
        os.makedirs(g_cnfg_dir)
    
    if not os.path.exists(g_temp_dir):
        # create tmp directory
        os.makedirs(g_temp_dir)

#=======================================================================================
class ConfigManager(object):
    '''
    Configuration reader
    '''

#=======================================================================================
    def __init__(self):
#=======================================================================================
        '''
        Constructor
        '''
        
        init_app_env()   
        
        # save dirname-dirpath 
        self.__repo_config = {}     
        
        # save repository objects for auto-save function
        # key:name value:path
        self.__auto_save_repos = {}
        
        self.__auto_save_interval = 0
        
        self.__compare_cmd = ''
        # read config file
        self.read_config()
        
#=======================================================================================
    def read_config(self):
#=======================================================================================
        '''
        description: read config file
        ''' 
        global g_default_compare_tool
        
        # get configuration from file
        self.cfg_xml_tree = ET.parse(g_repo_file)
        self.root = self.cfg_xml_tree.getroot()
        
        # read config of default compare tool
        compare_tool_cfg = self.root.find('compare-tool')
        if compare_tool_cfg != None:
            self.__compare_cmd = compare_tool_cfg.find('default-cmd').text
            if self.__compare_cmd == None or len(self.__compare_cmd) == 0:
                self.__compare_cmd = g_default_compare_tool
        
        # read auto save function
        auto_save = self.root.find('auto-save-config')
        if auto_save != None:
            interval = auto_save.find('time-interval').text
            try:
                self.__auto_save_interval = int(interval)
            except ValueError:
                report_exception("auto-save interval must be integer, check config file!")
                self.__auto_save_interval = 0
                
        
        for repository in self.root.findall('repository'):
            name = repository.find('name').text
            path = repository.find('path').text
            self.__repo_config[name] = path
            
            auto_save = repository.get('auto-save')
            if auto_save == "yes":
                self.__auto_save_repos[name] = "yes"
            else:
                self.__auto_save_repos[name] = "no"


#=======================================================================================
    def find_repo_in_xml(self, repo_name):
#=======================================================================================
        '''
        description: find a repository node object and return it
    
        parameter: repo_name, name of repository node 
        return   : repository node object if it found in config file otherwise return none
        ''' 
        for repository in self.root.findall('repository'):
            name = repository.find('name').text
            if name == repo_name:
                return repository
        
        return None
    
#=======================================================================================
    def remove_repo_node(self, repo_name):
#=======================================================================================
        '''
        description: delete repository from config file
    
        parameter: repo_name, name of repository node 
        ''' 
        if repo_name not in self.__repo_config:
            return
        
        # find the repository node by given repository name
        repo_node = self.find_repo_in_xml(repo_name)
        if repo_node is None:
            return
        else:
            # remove the node from root
            self.root.remove(repo_node)
            # update the repository xml file
            self.cfg_xml_tree.write(g_repo_file);
            # update config in memory
            del self.__repo_config[repo_name]

#=======================================================================================
    def add_repo_node(self, repo_name, repo_dir):
#=======================================================================================
        '''
        description: add repository to config file
    
        parameter: repo_name, name of repository node 
        parameter: repo_dir, repository directory
        ''' 
        # create node for config xml file
        repo_node = ET.SubElement(self.root, "repository")
        repo_node.set('auto-save', 'no')
        node_name = ET.SubElement(repo_node, "name")
        node_name.text = repo_name
        node_path = ET.SubElement(repo_node, "path")
        node_path.text = repo_dir
        
        # write a new repository node to xml file
        self.cfg_xml_tree.write(g_repo_file);
        
        # update repository config in memory
        self.__repo_config[repo_name] =repo_dir

#=======================================================================================
    def modify_repo_node(self, repo_name, **kwargs):
#=======================================================================================
        '''
        description: modify child node and attribute of repository in config file
    
        parameter: repo_name, name of repository node 
        parameter: kwargs, dictionary key (child node and attribute) and value
        ''' 
        repo_node = self.find_repo_in_xml(repo_name)
        for key, value in kwargs.items():
            if value != "yes" and value != "no":
                return
            if key == 'auto_save':
                repo_node.set('auto-save', value)
                self.cfg_xml_tree.write(g_repo_file);
        
#=======================================================================================
    def get_repo_config(self):
#=======================================================================================
        '''
        description: get repository in config
        return   : return self.__repo_config
        ''' 
        return self.__repo_config
        
#=======================================================================================
    def is_repo_name_valid(self, repo_name):
#=======================================================================================
        '''
        description: check if repository node existed in config
    
        parameter: repo_name, name of repository node 
        return   : return true if it existed in self.__repo_config
        ''' 
        if repo_name in self.__repo_config:
            return False
        return True
    
#=======================================================================================
    def get_auto_saved_repo(self):
#=======================================================================================
        '''
        description: get auto saved repository dictionary
        return   : return auto saved repository dictionary
        '''   
        return self.__auto_save_repos

#=======================================================================================
    def set_auto_saved_repo(self, repo_name, value):
#=======================================================================================
        '''
        description: set auto-save attribute for repository node
    
        parameter: repo_name, name of repository node 
        parameter: value,  "yes" or "no" for auto-save attribute of repository node
        return   : return true if set successfully otherwise false
        '''    
        if repo_name not in self.__repo_config:
            return
        
        if value != "yes" and value != "no":
            return
        
        self.__auto_save_repos[repo_name] = value
        self.modify_repo_node(repo_name, auto_save=value)
    
    
#=======================================================================================
    def modify_auto_saved_config(self, auto_save_repos):
#=======================================================================================
        '''
        description: modify auto saving in config file
    
        parameter: auto_save_config, name of repository node 
        '''    
        
        for repo_name, is_save in auto_save_repos.iteritems():
            self.set_auto_saved_repo(repo_name, is_save)

#=======================================================================================            
    def set_auto_save_interval(self, new_interval):
#=======================================================================================
        '''
        description: modify value of time-interval of auto-save in config file
    
        parameter: new_interval, new interval for auto saving, unit: minute
        ''' 
        auto_save_config = self.root.find('auto-save-config')
        if auto_save_config == None:
            # create new config for auto save
            self.__create_auto_config(new_interval)
            return
        else:
            
            time_interval_node = auto_save_config.find('time-interval')
            # create new auto_save item
            if time_interval_node == None:
                time_interval_node = ET.SubElement(auto_save_config, "time-interval")
                self.cfg_xml_tree.write(g_repo_file);
                return
            # update item 
            else:
                time_interval_node.text = str(new_interval)
                self.cfg_xml_tree.write(g_repo_file);
                return
        
#=======================================================================================          
    def __create_auto_config(self, new_interval):
#=======================================================================================  
        '''
        description: create auto_save item in config file
        ''' 
        auto_save_config = ET.SubElement(self.root, "auto-save-config")
        auto_save_item = ET.SubElement(auto_save_config, "time-interval")
        auto_save_item.text = str(new_interval)
        
        # write a new repository node to xml file
        self.cfg_xml_tree.write(g_repo_file);
        
#=======================================================================================            
    def get_auto_save_interval(self):
#=======================================================================================
        '''
        description: get auto_save intervel from config file
        '''    
        return self.__auto_save_interval

#=======================================================================================            
    def get_temp_dir(self):
#=======================================================================================
        '''
        description: get temp directory for comparison
        '''  
        global g_temp_dir
          
        return g_temp_dir

#=======================================================================================            
    def get_work_dir(self):
#=======================================================================================
        '''
        description: get DM work directory
        '''  
        global g_work_dir
          
        return g_work_dir

#=======================================================================================            
    def set_compare_tool(self, compare_cmd):
#=======================================================================================
        '''
        description: set default copmare tool and write it to config file
        parameter  : compare tool command (absolute full path)
        '''  
        self.__compare_cmd = compare_cmd
        
        # read config of default comparison tool
        compare_tool_cfg = self.root.find('compare-tool')
        
        if compare_tool_cfg != None:
            default_cmd = compare_tool_cfg.find('default-cmd')
            default_cmd.text = compare_cmd
            self.cfg_xml_tree.write(g_repo_file);
            return
        
        else:
            # create new config for comparison tool
            compare_tool_node = ET.SubElement(self.root, "compare-tool")
            cmd_node = ET.SubElement(compare_tool_node, "default-cmd")
            cmd_node.text = compare_cmd
            
            # write a new repository node to xml file
            self.cfg_xml_tree.write(g_repo_file);
            return

#=======================================================================================            
    def get_compare_tool(self):
#=======================================================================================
        '''
        description: get default copmare tool from config file
        ''' 
        global g_default_compare_tool
        if self.__compare_cmd == '' or self.__compare_cmd == None or len(self.__compare_cmd) == 0:
            return g_default_compare_tool
        
        return self.__compare_cmd
        